home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Frameworks / TransSkel 3.24 / Demos / C Demos / MultiSkel / MSkelZoom.c < prev    next >
Text File  |  1994-07-14  |  5KB  |  234 lines

  1. /*
  2.  * TransSkel multiple-window demonstration: ZoomRect module
  3.  * 
  4.  * This module handles a window in which successive randomly generated
  5.  * rectangles are smoothly interpolated into one another.  The display
  6.  * is white on black, which results in some interesting problems (see
  7.  * ZDrawGrowBox, for instance).  The display adjusts itself to the size
  8.  * of the window, so that the zoom series always lie entirely within
  9.  * the window.  Clicking the mouse in the window pauses the display until
  10.  * the button is released.
  11.  * 
  12.  * 21 Apr 88 Paul DuBois
  13.  * 29 Jan 89
  14.  * - Conversion for TransSkel 2.0.
  15.  * 12 Jan 91
  16.  * - Conversion to TransSkel 3.0.  Turning on prototyping uncovered
  17.  * a couple of (harmless) argument-passing mistakes.  Ahem.
  18.  * 20 Dec 93
  19.  * - Fixed grow box drawing so it draws correctly in white-on-black
  20.  * even when system normally draws color-tinged grow boxes.
  21.  */
  22.  
  23. # include    "TransSkel.h"
  24.  
  25. # include    "MultiSkel.h"
  26.  
  27.  
  28. # define    zoomSteps    15        /* # rects in interpolative series */
  29.  
  30.  
  31. static void ZDrawGrowBox (WindowPtr wind);
  32.  
  33.  
  34. static Rect        zRect[zoomSteps];    /* set of interpolated rectangles */
  35. static Rect        zSrcRect;
  36. static short    sizeX;                /* size of window in pixels */
  37. static short    sizeY;
  38.  
  39.  
  40. static void
  41. SetZoomSize (void)
  42. {
  43. Rect    r;
  44.  
  45.     r = zoomWind->portRect;
  46.     r.right -= 15;                /* don't use right edge */
  47.     sizeX = r.right;
  48.     sizeY = r.bottom;
  49. }
  50.  
  51.  
  52. /*
  53.  * return integer between zero and max (inclusive).  assumes max is
  54.  * non-negative.
  55.  */
  56.  
  57. static short
  58. Rand (short max)
  59. {
  60. short    t;
  61.  
  62.     t = Random ();
  63.     if (t < 0) t = -t;
  64.     return (t % (max + 1));
  65. }
  66.  
  67.  
  68. /*
  69.  * Interpolate one rectangle smoothly into another.  Erase the previous
  70.  * series as the new one is drawn.
  71.  */
  72.  
  73. static void
  74. ZoomRect (Rect *r1, Rect *r2)
  75. {
  76. short    r1left, r1top;
  77. short    l, t;
  78. short    j;
  79. short    hDiff, vDiff, widDiff, htDiff;
  80. short    r, b;
  81. short    rWid, rHt;
  82.  
  83.     r1left = r1->left;
  84.     r1top = r1->top;
  85.     hDiff = r2->left - r1left;    /* positive if moving to right */
  86.     vDiff = r2->top - r1top;        /* positive if moving down */
  87.     rWid = r1->right - r1left;
  88.     rHt = r1->bottom - r1top;
  89.     widDiff = (r2->right - r2->left) - rWid;
  90.     htDiff = (r2->bottom - r2->top) - rHt;
  91.     /*
  92.      * order of evaluation is important in the rect coordinate calculations.
  93.      * since all arithmetic is integer, you can't save time by calculating
  94.      * j/zoomSteps and using that - it'll usually be zero.
  95.      */
  96.     for (j = 1; j <= zoomSteps; j++)
  97.     {
  98.         FrameRect (&zRect[j-1]);                /* erase a rectangle */
  99.         l = r1left + (hDiff * j) / zoomSteps;
  100.         t = r1top + (vDiff * j) / zoomSteps;
  101.         r = l + rWid + (widDiff * j) / zoomSteps;
  102.         b = t + rHt + (htDiff * j) / zoomSteps;
  103.         SetRect (&zRect[j-1], l, t, r, b);
  104.         FrameRect (&zRect[j-1]);
  105.     }
  106. }
  107.  
  108.  
  109. /*
  110.  * Draw the grow box in white on black.  I used to do this by drawing the box and
  111.  * inverting it, but that doesn't work under System 7 which uses color tinges.
  112.  * Now I just draw the squares directly.  Ugh.
  113.  */
  114.  
  115. static void
  116. ZDrawGrowBox (WindowPtr wind)
  117. {
  118. Rect    r;
  119.  
  120.     r = wind->portRect;
  121.     r.left = r.right - 15;
  122.     r.top = r.bottom - 15;
  123.     ++r.right;
  124.     ++r.bottom;
  125.     EraseRect (&r);
  126.     FrameRect (&r);
  127.     if (((WindowPeek) wind)->hilited)
  128.     {
  129.         r.right -= 6;
  130.         r.bottom -= 6;
  131.         OffsetRect (&r, 4, 4);
  132.         FrameRect (&r);
  133.         r.right -= 3;
  134.         r.bottom -= 3;
  135.         OffsetRect (&r, -1, -1);
  136.         EraseRect (&r);
  137.         FrameRect (&r);
  138.     }
  139. }
  140.  
  141.  
  142. /*
  143.  * just pause zoom display while mouse down
  144.  */
  145.  
  146. static pascal void
  147. Mouse (Point pt, long t, short mods)
  148. {
  149.     while (StillDown ()) {  /* wait until mouse button released */ }
  150. }
  151.  
  152.  
  153. static pascal void
  154. Update (Boolean resized)
  155. {
  156. short    i;
  157.  
  158.     EraseRect (&zoomWind->portRect);
  159.     ZDrawGrowBox (zoomWind);
  160.     SetWindClip (zoomWind);
  161.     for (i = 0; i < zoomSteps; ++i)
  162.         FrameRect (&zRect[i]);
  163.     ResetWindClip ();
  164.     if (resized)
  165.         SetZoomSize ();        /* adjust to new window size */
  166. }
  167.  
  168.  
  169. static pascal void
  170. Activate (Boolean active)
  171. {
  172.  
  173.     ZDrawGrowBox (zoomWind);
  174.     if (active)
  175.         DisableItem (editMenu, 0);
  176.     else
  177.         EnableItem (editMenu, 0);
  178.     DrawMenuBar ();
  179. }
  180.  
  181.  
  182. static pascal void
  183. Clobber (void)
  184. {
  185.     DisposeWindow (zoomWind);
  186. }
  187.  
  188.  
  189. static pascal void
  190. Idle (void)
  191. {
  192. short    i;
  193. Point    pt1, pt2;
  194. Rect    dstRect;
  195.  
  196.     SetPt (&pt1, Rand (sizeX), Rand (sizeY));    /* generate new rect */
  197.     SetPt (&pt2, Rand (sizeX), Rand (sizeY));    /* and zoom to it */
  198.     Pt2Rect (pt1, pt2, &dstRect);
  199.     SetWindClip (zoomWind);            /* don't draw in right edge */
  200.     ZoomRect (&zSrcRect, &dstRect);
  201.     ResetWindClip ();
  202.     zSrcRect = dstRect;
  203. }
  204.  
  205.  
  206. void
  207. ZoomWindInit (void)
  208. {
  209. short    i;
  210.  
  211.     if (SkelQuery (skelQHasColorQD))
  212.         zoomWind = GetNewCWindow (zoomWindRes, nil, (WindowPtr) -1L);
  213.     else
  214.         zoomWind = GetNewWindow (zoomWindRes, nil, (WindowPtr) -1L);
  215.     if (zoomWind == (WindowPtr) nil)
  216.         return;
  217.     (void) SkelWindow (zoomWind,
  218.                 Mouse,        /* pause while button down */
  219.                 nil,        /* ignore key clicks */
  220.                 Update,
  221.                 Activate,
  222.                 nil,        /* no close proc */
  223.                 Clobber,    /* disposal proc */
  224.                 Idle,        /* draw a new series */
  225.                 false);
  226.  
  227.     SetZoomSize ();
  228.     BackPat ((ConstPatternParam) &qd.black);
  229.     PenMode (patXor);
  230.     SetRect (&zSrcRect, 0, 0, 0, 0);
  231.     for (i = 0; i < zoomSteps; ++i)        /* initialize rect array */
  232.         zRect[i] = zSrcRect;
  233. }
  234.